﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RainEngine.SceneManagement;

namespace RainEngine.SceneNodes.UI
{
    /// <summary>
    /// 下列列表框
    /// </summary>
    public class UIComboBox :UISceneNode 
    {
        //默认值
        private static readonly float DefaultComboBoxWidth = 160.0f;
        private static readonly float DefaultScrollBarWidth = 16.0f;
        private static readonly float DefaultListBoxHeight = 92.0f;
        private static readonly Rectangle DefaultTextBoxRect = new Rectangle(1, 1, 6, 6);
        private static readonly Rectangle DefaultButtonRectOrigin = new Rectangle(0, 16, 16, 16);
        private static readonly Rectangle DefaultButtonRectHighlight = new Rectangle(16, 16, 16, 16);        
        private static readonly Rectangle DefaultButtonRectChecked = new Rectangle(0, 48, 16, 16);
        private static readonly Rectangle DefaultButtonRectCheckedHighlight = new Rectangle(16, 48, 16, 16);        
        
        /// <summary>
        /// 下拉列表框右侧的复选框控件
        /// </summary>
        UICheckBox button;

        /// <summary>
        /// 列表框控件
        /// </summary>
        UIListBox listbox;

        /// <summary>
        /// 列表框高度，默认为92。它的宽度无需指定，等于下拉列表框宽度，默认为160。
        /// </summary>
        private float listBoxHeight;

        /// <summary>
        /// 滚动条宽度，默认为16。
        /// </summary>
        float scrollBarWidth;        

        /// <summary>
        /// 下拉列表框的宽度，默认为160。
        /// </summary>
        float width;
        
        /// <summary>
        /// 文本框中的文字。
        /// </summary>
        private string text;        

        /// <summary>
        /// 文字使用的字体。
        /// </summary>
        private SpriteFont font;        

        /// <summary>
        /// 文本使用的颜色
        /// </summary>
        private Color textColor;

        /// <summary>
        /// 文本框背景图像矩形
        /// </summary>
        private Rectangle textBoxRect;        

        /// <summary>
        /// 按钮普通状态图像矩形
        /// </summary>
        private Rectangle buttonRectOrigin;        

        /// <summary>
        /// 按钮高亮状态图像矩形
        /// </summary>
        private Rectangle buttonRectHighlight;        

        /// <summary>
        /// 按钮选中状态图像矩形
        /// </summary>
        private Rectangle buttonRectChecked;        

        /// <summary>
        /// 按钮选中时高亮状态图像矩形
        /// </summary>
        private Rectangle buttonRectCheckedHighlight;        

        /// <summary>
        /// 当选中的文字项发生改变时引发的事件。
        /// </summary>
        public event EventHandler SelectionChanged = null;
        
        /// <summary>
        /// 列表框是否处于打开状态。
        /// </summary>
        bool justOpened = false;        
        
        /// <summary>
        /// 创建一个默认ComboBox，文字项数组为空。
        /// </summary>
        /// <param name="engine">引擎</param>
        /// <param name="setScene">所属场景</param>
        public UIComboBox(RainGE engine, Scene setScene):this(engine ,setScene ,null)
        {
            
        }

        /// <summary>
        /// 创建一个ComboBox，需要传递文字项数组
        /// </summary>
        /// <param name="engine">引擎</param>
        /// <param name="setScene">所属场景</param>
        /// <param name="setItems">文字项数组</param>
        public UIComboBox(RainGE engine, Scene setScene,string [] setItems)
            : this(engine, setScene, Vector2.Zero, "UITextBox", DefaultComboBoxWidth,DefaultListBoxHeight ,DefaultScrollBarWidth,engine.DefaultFont, Color.White,DefaultTextBoxRect ,DefaultButtonRectOrigin ,DefaultButtonRectHighlight ,DefaultButtonRectChecked ,DefaultButtonRectCheckedHighlight ,setItems,true)
        {

        }

        /// <summary>
        /// 创建一个UIComboBox，内部方法，只能在引擎内部调用。
        /// </summary>
        /// <param name="engine">引擎</param>
        /// <param name="setScene">所属场景</param>
        /// <param name="setPosition">控件的2D屏幕位置</param>
        /// <param name="setTextureName">纹理名称</param>
        /// <param name="setWidth">下拉列表框宽度</param>
        /// <param name="setListBoxHeight">列表框高度</param>
        /// <param name="setScrollBarWidth">滚动条宽度</param>
        /// <param name="setFont">文字使用的字体</param>
        /// <param name="setTextColor">文字颜色</param>
        /// <param name="setTextBoxRect">文本框图像矩形</param>
        /// <param name="setButtonRectOrigin">按钮普通状态图像矩形</param>
        /// <param name="setButtonHighlight">按钮高亮状态图像矩形</param>
        /// <param name="setButtonRectChecked">按钮选中状态图像矩形</param>
        /// <param name="setButtonRectCheckedHighlight">按钮选中时高亮状态图像矩形</param>
        /// <param name="setItems">文字项数组</param>
        internal UIComboBox(RainGE engine, Scene setScene, Vector2 setPosition,string setTextureName,float setWidth,float setListBoxHeight,float setScrollBarWidth,SpriteFont setFont,Color setTextColor,Rectangle setTextBoxRect,Rectangle setButtonRectOrigin,Rectangle setButtonHighlight,Rectangle setButtonRectChecked,Rectangle setButtonRectCheckedHighlight,string [] setItems,bool useResource) : base(engine, setScene, setPosition, setTextureName,useResource ) 
        {
            this.font =setFont ;
            this.textColor = setTextColor;
            this.width = setWidth;
            this.scrollBarWidth = setScrollBarWidth;
            this.listBoxHeight = setListBoxHeight;
            this.size=new Vector2 (width ,font .LineSpacing );

            this.textBoxRect =setTextBoxRect ;
            this.buttonRectOrigin = setButtonRectOrigin;
            this.buttonRectHighlight = setButtonHighlight;
            this.buttonRectChecked = setButtonRectChecked;
            this.buttonRectCheckedHighlight = setButtonRectCheckedHighlight;
           
            //初始化并添加一个下拉按钮，实际上是一个不含文字的复选框
            button = new UICheckBox(engine, setScene, new Vector2(Position.X + size.X - size.Y, Position.Y), "UIScrollBar", new Vector2(size.Y, size.Y), null, engine.DefaultFont, Color.White, Color.White, buttonRectOrigin, buttonRectHighlight, buttonRectChecked, buttonRectCheckedHighlight,true);
            button.TabStop = false;
            button.CheckedChanged +=new EventHandler(button_CheckedChanged);
            this.Scene.AddNode(button);

            //初始化并添加一个列表框
            if(setItems !=null)
                listbox = new UIListBox(engine ,setScene,setItems);
            else
                listbox = new UIListBox(engine, setScene);
            listbox.ChangeSelection +=new EventHandler(listbox_ChangeSelection);
            listbox .MouseClick +=new System.Windows.Forms.MouseEventHandler(listbox_MouseClick);
            listbox.TabStop = false;            
            this.Scene.AddNode(listbox);
            
            //鼠标点击下拉列表框时控制列表框的可见与否，其实就是调用按钮的点击事件
            this.MouseClick += new System.Windows.Forms.MouseEventHandler(combo_MouseClick);
            
            //绘制下拉列表框
            Redraw();
        }        

        #region 属性
        
        /// <summary>
        /// 获取或设置文本框中的文字
        /// </summary>
        public string Text
        {
            get { return text; }
        }

        /// <summary>
        /// 获取或设置文本使用的字体
        /// </summary>
        public SpriteFont Font
        {
            get { return font; }
            set
            {
                font = value;
                listbox.Font = value;
            }
        }

        /// <summary>
        /// 获取或设置文本使用的颜色
        /// </summary>
        public Color TextColor
        {
            get { return textColor; }
            set { textColor = value; }
        }

        /// <summary>
        /// 获取或设置文本框背景图像矩形
        /// </summary>
        public Rectangle TextBoxRect
        {
            get { return textBoxRect; }
            set { textBoxRect = value; }
        }

        /// <summary>
        /// 获取或设置按钮普通状态图像矩形
        /// </summary>
        public Rectangle ButtonRectOrigin
        {
            get { return buttonRectOrigin; }
            set { buttonRectOrigin = value; }
        }

        /// <summary>
        /// 获取或设置按钮高亮状态图像矩形
        /// </summary>
        public Rectangle ButtonRectHighlight
        {
            get { return buttonRectHighlight; }
            set { buttonRectHighlight = value; }
        }

        /// <summary>
        /// 获取或设置按钮选中状态图像矩形
        /// </summary>
        public Rectangle ButtonRectChecked
        {
            get { return buttonRectChecked; }
            set { buttonRectChecked = value; }
        }

        /// <summary>
        /// 获取或设置按钮选中时高亮状态图像矩形
        /// </summary>
        public Rectangle ButtonRectCheckedHighlight
        {
            get { return buttonRectCheckedHighlight; }
            set { buttonRectCheckedHighlight = value; }
        }

        /// <summary>
        /// 获取或设置滚动条宽度，默认为16。
        /// </summary>
        public float ScrollBarWidth
        {
            get { return listbox.ScrollBarWidth;}
            set { listbox.ScrollBarWidth = value; }
        }

        /// <summary>
        /// 获取或设置选中文字项的文字
        /// </summary>
        public string SelectedItem
        {
            get
            {
                return listbox.SelectedItem;
            }
            set
            {
                listbox.SelectedItem = value;
                text = listbox.SelectedItem; 
            }
        }

        /// <summary>
        /// 获取选中的文字项的索引
        /// </summary>
        public int SelectedIndex
        {
            get { return listbox.SelectedIndex; }
            set
            {
                listbox.SelectedIndex = value;
                text = listbox[value];
            }
        }

        /// <summary>
        /// 获取或设置列表框的文字项数组
        /// </summary>
        public List<string> Items { get { return listbox.Items; } set { listbox.Items = value; } }

        /// <summary>
        /// 获取列表框是否被显示
        /// </summary>
        public bool Opened { get { return listbox.Visible; } }

        #endregion

        #region 事件相关方法

        /// <summary>
        /// 在文字项数组中添加一个数据项
        /// </summary>
        public void AddItem(string item)
        {
            listbox.AddItem(item);
            if (!justOpened)
                listbox.Visible = false;
        }

        /// <summary>
        /// 下列列表框位置改变时需要重新绘制。
        /// </summary>
        protected override void OnLocationChanged()
        {
            Redraw();
            base.OnLocationChanged();
        }

        /// <summary>
        /// 下列列表框大小改变时需要重新绘制。
        /// </summary>
        protected override void OnSizeChanged()
        {
            Redraw();
            base.OnSizeChanged();
        }

        protected override void OnVisibleChanged(EventArgs e)
        {
            base.OnVisibleChanged(e);
            button.Visible = visible;
            if(justOpened )
                listbox.Visible =visible ;
        }

        /// <summary>
        /// 重新绘制下列列表框。
        /// </summary>
        private void Redraw()
        {
            this.size = new Vector2(size.X, font.LineSpacing);
            
            button.Position = new Vector2(Position.X + size.X - size.Y, Position.Y);

            listbox.Size = new Vector2(width, listBoxHeight);
            listbox.ScrollBarWidth = scrollBarWidth;            
            listbox.Position = new Vector2(Position.X, Position.Y + size.Y);
            listbox.Font = font;
            listbox.Size = new Vector2(size.X, listbox .Size .Y);
            if (!justOpened)
                listbox.Visible = false;
        }

        /// <summary>
        /// 点击列表框关闭列表框
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void listbox_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            listbox.Visible = false;
        }       

        /// <summary>
        /// 将文本框中的文字设置为选中的文字项，如果选中的文字项发生变化则引发SelectionChanged事件。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void listbox_ChangeSelection(object sender, EventArgs e)
        {
            string previousItem = text;
            text = listbox.SelectedItem;

            if (text != previousItem && SelectionChanged != null)
                SelectionChanged(listbox.SelectedItem, null);
            Close();
        }        

        /// <summary>
        /// 点击控件相当于点击右侧按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void combo_MouseClick(object sender, EventArgs e)
        {
            button.OnCheckedChanged(e);
        }

        /// <summary>
        /// 点击按钮打开列表框
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void button_CheckedChanged(object sender, EventArgs e)
        {
            if (visible)
            {
                if (!listbox.Visible)
                    Open();
                else
                    Close();
            }
        }

        /// <summary>
        /// 打开列表框
        /// </summary>
        private void Open()
        {
            justOpened = true;
            listbox.Visible = true;
        }

        /// <summary>
        /// 关闭列表框
        /// </summary>
        private void Close()
        {
            listbox.Visible = false;
            justOpened = false;
        }

        #endregion

        /// <summary>
        /// 绘制控件
        /// </summary>
        public override int Draw(GameTime gameTime)
        {
            //获取图像淡入淡出的透明颜色
            alphaTextureColor = new Color(Color.R, Color.G, Color.B, Scene.TransitionAlpha);

            //绘制文本框背景
            RainGE.SpriteBatch.Draw(texture, new Rectangle((int)Position.X, (int)(Position.Y), (int)(size.X - size.Y), (int)size.Y), textBoxRect, alphaTextureColor, Rotation, Origin, SpriteEffect, LayerDepth);
            //绘制文本框上的文字
            if (text != null)
                RainGE.SpriteBatch.DrawString(font, text, Position, textColor);
            return 1;

        }
    }
}
